#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using namespace std;

struct TreeNode {
    int val;
    TreeNode* left;
    TreeNode* right;
    TreeNode() : val(0), left(nullptr), right(nullptr) {}
    TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
    TreeNode(int x, TreeNode* left, TreeNode* right) : val(x), left(left), right(right) {}
};

vector<TreeNode*> ans = vector<TreeNode*>();
unordered_map<TreeNode*, string> mp;
string serialize(TreeNode* root) {
    if (!root) {
        return "#";
    } else {
        string left, right;
        if (mp.count(root->left)) {
            left = mp[root->left];
        } else {
            left = serialize(root->left);
        }
        if (mp.count(root->right)) {
            right = mp[root->right];
        } else {
            right = serialize(root->right);
        }
        string ans = to_string(root->val) + ',' + left + ',' + right;
        mp[root] = ans;
        return ans;
    }
}

vector<TreeNode*> findDuplicateSubtrees(TreeNode* root) {
    serialize(root);
    vector<TreeNode*> ans;
    unordered_map<string, int> cnt;
    for(auto& it : mp){
        if(!cnt.count(it.second)){
            cnt[it.second]++;
        }else if(cnt[it.second] == 1){
            ans.emplace_back(it.first);
            cnt[it.second]++;
        }
    }
    return ans;
}